<template>
  <DialogAndBlock
    ref="DialogAndBlockRef"
    title="上传文件"
    class="UploadFile">
    <div class="progress">
      <el-checkbox v-model="whetherTheFil"
                   true-value="1"
                   false-value="0"
                   label="同名文件是否覆盖" size="large" />
    </div>
    <div class="el-upload-dragger"
         @dragleave.stop.prevent
         @dragover.stop.prevent
         @dragend.stop.prevent
         @drop.stop.prevent="handleDrop"
         ref="fileUploadRef">
      <div class="el-upload__text">
        <em>
          {{ noDragDropSupport ? '浏览器不支持拖拽上传,' : `将文件/文件夹拖到此处, ` }}
        </em>
      </div>
      <div class="uploadIcons">
        <div @click.stop="handleFileClick">
          <el-icon class="el-icon--upload">
            <Document />
          </el-icon>
          <div>
            点击上传文件
          </div>
        </div>
        <div @click.stop="handleDirectoryClick">
          <el-icon class="el-icon--upload">
            <Folder  />
          </el-icon>
          <div>
            点击上传文件夹
          </div>
        </div>
      </div>
    </div>
    <div class="progress" v-for="(item,index) in uploadProgressList"
         :key="index+'uploadProgressList'+item.webkitRelativePath">
      <el-progress :percentage="item.uploadProgress"
                   :color="customColors" />
      <div>
        {{item.name}}
      </div>
    </div>
    <div class="progress" v-if="uploadFileCount>0">
      <el-progress :percentage="allPercentage"
                   :color="customColors" />
      <div>
        上传总进度
      </div>
    </div>
    <div class="progress" v-if="uploadFileCount>0">
      还需要上传的文件个数：{{uploadFileCount}}
    </div>
    <div class="progress" v-if="errorFileList.length>0">
      <el-button
        type="primary"
        @click.stop="errFileUpload"
      >上传错误文件是否重新上传</el-button>
    </div>
    <input type="file" style="display: none" multiple
           @change="handleFileChange"
           ref="fileInputRef"/>
    <input type="file" webkitdirectory mozdirectory odirectory style="display: none"
           @change="handleDirectoryChange"
           ref="directoryInputRef"/>
  </DialogAndBlock>
</template>

<script lang="ts">
import {defineComponent} from 'vue'
import DialogAndBlock from "@/components/DialogAndBlock/index.vue";
import fileReq from "@/api/file";
import {RouteLocationNormalizedLoaded} from "vue-router";
import {getFilesFromDataTransferItemList} from "./Utils";
import LimitPromise from "@/utils/LimitPromise";
import pathBrowserify from "path-browserify";
import {PromiseErrorTryAgain} from "@/utils/PromiseErrorTryAgain";

const limitPromise = new LimitPromise(3)
export default defineComponent({
  name: "UploadFile",
  components: {DialogAndBlock},
  data(){
    return {
      basePath: '',
      uploadFileCount: 0,
      uploadProgressList: [],
      noDragDropSupport: false,
      customColors: [
        { color: '#f56c6c', percentage: 20 },
        { color: '#e6a23c', percentage: 40 },
        { color: '#1989fa', percentage: 60 },
        { color: '#6f7ad3', percentage: 80 },
        { color: '#5cb87a', percentage: 100 },
      ],
      call:null,
      errorFileList: [],
      allFileSize: 0,
      uploadedFileSize: 0,
      whetherTheFil: '1',
    }
  },
  created() {
    this.noDragDropSupport= !this.checkDragDropSupport()
  },
  methods: {
    open(basePath?:string,call?:()=>void) {
      if(!this.disabled){
        this.basePath = basePath || '/'
        // @ts-ignore
        this.call = call
      }
      this.$refs.DialogAndBlockRef.open()
    },
    handleFileClick() {
      // @ts-ignore
      this.$refs.fileInputRef.click()
    },
    handleDirectoryClick(){
      // @ts-ignore
      this.$refs.directoryInputRef.click()
    },
    handleDrop(e){
      // e.dataTransfer.items是一个DataTransferItemList对象，包含了拖拽的文件
      getFilesFromDataTransferItemList(e.dataTransfer.items,(file,webkitRelativePath)=>{
        // 处理文件
        this.uploadFile(file,webkitRelativePath)
      })
    },
    handleFileChange(e) {
      // 获取文件
      const files = e.target.files
      // 遍历文件，单个文件调用handleFile方法
      Array.from(files).map(file => {
        // 处理文件
        this.uploadFile(file as File,file.name)
      })
      // @ts-ignore
      this.$refs.fileInputRef.value = null
    },
    handleDirectoryChange (e) {
      // 获取文件夹
      // 遍历文件，单个文件调用handleFile方法
      const files = e.target.files
      Array.from(files).map(file => {
        // 处理文件
        this.uploadFile(file as File,file.webkitRelativePath)
      })
      // @ts-ignore
      this.$refs.directoryInputRef.value = null
    },
    checkDragDropSupport() {
      const div = document.createElement('div');
      let result = ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
      div.remove()
      return result
    },
    uploadFile(file:File,webkitRelativePath:string) {
      if(this.disabled) {
        return
      }
      this.uploadFileCount++
      let basePath = '/'
      if (this.basePath !== '/dashboard') {
        basePath = this.basePath.replace("/dashboard", "")
      }
      basePath = pathBrowserify.resolve(basePath,webkitRelativePath)
      this.allFileSize+=file.size
      let whetherTheFil = this.whetherTheFil
      limitPromise.call(() => PromiseErrorTryAgain(() => {
        const item = {
          webkitRelativePath,
          name: file.name,
          uploadProgress: 0,
          file,
          loaded: 0,
        }
        this.uploadProgressList.push(item)
        return fileReq.uploaderFile(basePath, file, whetherTheFil,(uploadProgress, params) => {
          const findIndex = this.uploadProgressList.findIndex(i => {
            return i.webkitRelativePath === item.webkitRelativePath
          })
          if (findIndex > -1) {
            this.uploadProgressList[findIndex].uploadProgress = uploadProgress
            this.uploadProgressList[findIndex].loaded = params.loaded
            this.uploadedFileSize+=params.diffLoaded
          }
        })
          .catch(() => {
            this.errorFileList.push({
              file,
              webkitRelativePath
            })
          })
          .finally(() => {
            this.uploadedFileSize+=(file.size - item.loaded)
            let findIndex = this.uploadProgressList.findIndex(i => {
              return i.webkitRelativePath === item.webkitRelativePath
            })
            if (findIndex > -1) {
              this.uploadProgressList.splice(findIndex, 1)
            }
            this.uploadFileCount--
            if (this.uploadFileCount === 0) {
              if(this.call) {
                // @ts-ignore
                this.call()
                this.call = null
              }
              this.uploadedFileSize = 0
              this.allFileSize = 0
            }
          })
      }))
    },
    errFileUpload() {
      this.errorFileList.forEach(item=>{
        this.uploadFile(item.file,item.webkitRelativePath)
      })
      this.errorFileList = []
    }
  },
  computed: {
    disabled() {
      const route = this.$route as RouteLocationNormalizedLoaded
      return !route.path.startsWith('/dashboard')
    },
    allPercentage() {
      if(this.allFileSize <=0){
        return 100
      }
      return (this.uploadedFileSize / this.allFileSize * 100).toFixed(2) / 1
    }
  }
})
</script>

<style lang="scss" scoped>
.UploadFile{
  .uploadIcons{
    display: flex;
    justify-content: space-around;
    margin-bottom: 20px;
    &>div{
      border: 1px dashed var(--el-border-color);
      border-radius: 6px;
      box-sizing: border-box;
      cursor: pointer;
      padding: 20px;
      &:hover {
        color: var(--el-color-primary);
        border-color: var(--el-color-primary);
        &>.el-icon--upload{
          color: var(--el-color-primary);
        }
      }
    }
  }
  .el-upload__text{
    margin-top: 20px;
    margin-bottom: 20px;
  }
  .progress{
    margin-top: 20px;
  }
}
</style>
